// copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
// see COPYRIGHT for reuse legalities
//

#import "RIBPointsPolygons.h"

@implementation RIBPointsPolygons

+ initialize { return [RIBPointsPolygons setVersion:1], self; }

- (BOOL)hasBoundingBox { return YES; }

- init
{
  [super init];

  nPolys = 0;
  nVertices = NULL;
  vertices = NULL;
  nPolysBuf = (char *)malloc(128);
  cntBuf = (char *)malloc(128);
  
  return self;
}

- free
{
  if (nVertices) { free(nVertices); }
  if (vertices) { free(vertices); }
  free(nPolysBuf);
  free(cntBuf);

  return [super free];
}


// this is used only internally, for setting a copy without freeing the original
- _setNVertices:(RtInt *)newNVertices vertices:(RtInt *)newVertices
{
  int  i, cnt = 0;


  if (newNVertices)
  {  nVertices =  (long *)NXZoneMalloc([self zone], nPolys*sizeof(long));
     for (i = 0; i < nPolys; i++)  
     {  nVertices[i] = newNVertices[i];
        cnt += nVertices[i];
     }
     vertices =  (long *)NXZoneMalloc([self zone], cnt*sizeof(long));
     for (i = 0; i < cnt; i++)  
     {  vertices[i] = newVertices[i];
     }
     
  }
  else
  {  nVertices = NULL;
     vertices = NULL;
  }
  return self;
}

- _reallocBufs  {  nPolysBuf = (char *)malloc(128);  cntBuf = (char *)malloc(128); return self; }

- copyFromZone:(NXZone *)zone
{
   id   newCopy = [super copyFromZone:zone];

  [newCopy _setNVertices:nVertices vertices:vertices];
  [newCopy _reallocBufs];
  return newCopy;
}


- setNPolys:(RtInt)newNPolys nVertices:(RtInt *)newNVertices vertices:(RtInt *)newVertices 
     n:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector
     printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
{  
   nPolys = newNPolys;
   nVertices = newNVertices;
   vertices = newVertices;
   [self setN:newN tokens:newTokens parms:newParms archiveVector:newArchiveVector printfTypeVector:newPrintfTypeVector printfNVector:newPrintfNVector];

   dirtyBoundingBox = TRUE;
   return self;
}

- setNPolys:(RtInt)newNPolys { nPolys = newNPolys; dirtyBoundingBox = TRUE; return self; }
- setNVertices:(RtInt *)newNVertices { nVertices = newNVertices; dirtyBoundingBox = TRUE; return self; }
- setVertices:(RtInt *)newVertices { vertices = newVertices; dirtyBoundingBox = TRUE; return self; }

- (RtInt)nPolys { return nPolys; }
- (RtInt *)nVertices { return nVertices; }
- (RtInt *)vertices { return vertices; }

- (BOOL)theSameAs:otherRIBCommand
{
  int    i,
         nVerticesSum = 0;
  RtInt  *otherNVertices, *otherVertices;


  if ([self class] != [otherRIBCommand class])
  {  return NO;
  }
  if (nPolys != [otherRIBCommand nPolys])
  {  return NO;
  }

  otherNVertices = [otherRIBCommand nVertices];
  for (i = 0; i < nPolys; i++)
  {  if (nVertices[i] != otherNVertices[i])
     {  return NO;
     }
     nVerticesSum += nVertices[i];
  }

  otherVertices = [otherRIBCommand vertices];
  for (i = 0; i < nVerticesSum; i++)
  {  if (vertices[i] != otherVertices[i])
     {  return NO;
     }
  }

  return [super theSameAs:otherRIBCommand];
}


- (BOOL)similarTo:otherRIBCommand
{
  int    i,
         nVerticesSum = 0;
  RtInt  *otherNVertices, *otherVertices;


  if ([self class] != [otherRIBCommand class])
  {  return NO;
  }
  if (nPolys != [otherRIBCommand nPolys])
  {  return NO;
  }

  otherNVertices = [otherRIBCommand nVertices];
  for (i = 0; i < nPolys; i++)
  {  if (nVertices[i] != otherNVertices[i])
     {  return NO;
     }
     nVerticesSum += nVertices[i];
  }

  otherVertices = [otherRIBCommand vertices];
  for (i = 0; i < nVerticesSum; i++)
  {  if (vertices[i] != otherVertices[i])
     {  return NO;
     }
  }

  return [super theSameAs:otherRIBCommand];
}


- renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
{
  RiPointsPolygonsV(nPolys, nVertices, vertices, n, tokens, parms);
  return self;
}

- (BOOL)isMotionBlurrable { return YES; }

- writeEve:(NXStream *)stream atTabLevel:(int)tab
{
   int  i, sum = 0;


   for (i = 0; i < tab; i++)
   {  NXPrintf(stream, "\t");
   }
   NXPrintf(stream, "PointsPolygons {");
   for (i = 0; i < nPolys; i++)
   {  NXPrintf(stream, "%d ", nVertices[i]);
     sum += nVertices[i];
   }
   NXPrintf(stream, "} {");
   for (i = 0; i < sum; i++)
   {  NXPrintf(stream, "%d ", vertices[i]);
   }
   NXPrintf(stream, "} ");

   [super writeParameterList:stream];
   return self;
}

#define typeVector "l"
#define typeValues &nPolys

- read:(NXTypedStream*)stream 
{
    int version, i, cnt = 0;
    
    [super read:stream];
    nPolysBuf = (char *)malloc(128);
    cntBuf = (char *)malloc(128);
    version = NXTypedStreamClassVersion(stream,"RIBGeneralPolygon");
    if (version == 0) NXReadTypes(stream,"i",&version), version=1;
    if (version == 1) {
	NXReadTypes(stream,typeVector,typeValues);
	nVertices = (long *)NXZoneMalloc([self zone], nPolys*sizeof(long));
	NXReadArray(stream, "l", nPolys, nVertices);
	for (i = 0; i < nPolys; i++) {
	    cnt += nVertices[i];
	}
	vertices = (long *)NXZoneMalloc([self zone], cnt*sizeof(long));
	NXReadArray(stream, "l", cnt, vertices);
    } else {
    }
    return self;
}

- write:(NXTypedStream*)stream 
{
    int   i, cnt = 0;
    
    [super write:stream];
    NXWriteTypes(stream, typeVector, typeValues);
    NXWriteArray(stream, "l", nPolys, nVertices);
    for (i = 0; i < nPolys; i++) {
	cnt += nVertices[i];
    }
    NXWriteArray(stream, "l", cnt, vertices);
    return self;
}

@end
